package org.ouwh.fw.model;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.LogManager;
import org.apache.log4j.PropertyConfigurator;
import org.ouwh.fw.model.service.ServiceContainer;

public class ModelCore {
	private static Log log = LogFactory.getLog(ModelCore.class);
	private static ArrayList<ServiceOrderPair> services = new ArrayList<ServiceOrderPair>();
	private static AtomicBoolean running = new AtomicBoolean();

	public static String getConfigPath() {
		return System.getProperty("org.ouwh.fw.config.path", "conf");
	}

	public static void startup(Class<?> clazz) throws Exception {
		running.set(true);
		LogManager.resetConfiguration();
		PropertyConfigurator.configure(
				getConfigPath() + File.separator + System.getProperty("org.ouwh.fw.logging.config", "log4j.service"));
		log.info("*********************** Application starting... *************************");

		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				shutdown();
			}
		});

		Properties props = loadBootInfo(clazz);

		sortServices(props);
		log.info("Services start order: " + services);

		for (int i = 0; i < services.size(); i++) {
			ServiceContainer.loadService(services.get(i).service);
		}

		for (int i = 0; i < services.size(); i++) {
			ServiceContainer.startService(services.get(i).service);
		}

	}

	private static Properties loadBootInfo(Class<?> clazz) throws IOException {
		Properties props = new Properties();
		InputStream in = null;
		try {
			in = ModelCore.class.getResourceAsStream("/" + clazz.getName().replaceAll("\\.", "/") + ".boot");
			props.load(in);
		} finally {
			try {
				in.close();
			} catch (Exception e) {
			}
		}
		return props;
	}

	private static class ServiceOrderPair {
		String service;
		int order;

		public String toString() {
			return service + ":" + order;
		}
	}

	private static void sortServices(Properties props) {
		services.clear();
		Enumeration<?> e = props.keys();
		while (e.hasMoreElements()) {
			ServiceOrderPair pair = new ServiceOrderPair();
			pair.service = (String) e.nextElement();
			pair.order = Integer.parseInt(props.getProperty(pair.service));
			int pos = 0;
			for (int i = services.size() - 1; i >= 0; i--) {
				if (pair.order > services.get(i).order) {
					pos = i + 1;
					break;
				}
			}
			services.add(pos, pair);
		}
	}

	public static void shutdown() {
		// wait 0.5s
		try {
			Thread.sleep(500);
		} catch (Exception e) {
		}
		if (running.compareAndSet(true, false)) {
			log.info("####################### Application stopping... #########################");
			for (int i = services.size() - 1; i >= 0; i--) {
				try {
					ServiceContainer.stopService(services.get(i).service);
				} catch (Exception e) {
					log.error("stop service error", e);
				}
				services.remove(i);
			}
		}
	}

}
